package com.zf.annotation_reflect;

import java.lang.annotation.Annotation;
import java.lang.annotation.Target;
import java.lang.reflect.*;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 测试注解的获取和反射的使用
 */
public class AnnotationReflectTest {
    public static void main(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchFieldException {
        Class<Depart> cls = Depart.class;
        //获取类自身注解+父类注解（可以被继承的注解即@Inherited标记的注解）, 如果子类和父类有相同的注解，则只取子类的注解
        TableName[] annotation = cls.getAnnotationsByType(TableName.class);
        //获取类自身注解+父类注解（可以被继承的注解即@Inherited标记的注解）, 如果子类和父类有相同的注解，则只取子类的注解
        Annotation[] annotations = cls.getAnnotations();
        //获取类自身的注解，不会寻找父类的注解
        TableName[] declaredAnnotation = cls.getDeclaredAnnotationsByType(TableName.class);
        Annotation[] declaredAnnotations = cls.getDeclaredAnnotations();

        //是否存在指定的注解
        System.out.println(cls.isAnnotationPresent(Target.class));


        //如果覆盖了父类的属性，则新的属性不会继承父类属性的注解；否则可以继承
        //获取自身的public和继承public属性
        Field[] clsFields = cls.getFields();
        //获取自身的所有属性
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            System.out.print(field.getName() + " ");
            System.out.print(field.isAccessible() + " ");
            TableColumn fieldAnnotation = field.getAnnotation(TableColumn.class);
            Annotation[] annotations1 = field.getAnnotations();
            System.out.println(fieldAnnotation);
        }


        //如果重写了父类的方法，则父类方法上的注解不会被继承；否则可以继承
        //获取自身的public和继承public方法
        Method[] clsMethods = cls.getMethods();
        //获取自身的所有方法
        Method[] declaredMethods = cls.getDeclaredMethods();
        for (Method method : clsMethods) {
            System.out.print(method.getName()+" ");
            List<String> parameters = Arrays.stream(method.getParameters())
                    .map(Parameter::getName)
                    .collect(Collectors.toList());
            System.out.print(parameters.stream().collect(Collectors.joining(", "))+" ");
            System.out.println(method.isAccessible());

            if (method.getName().equals("testPdInter")) {
                //如果重写了父类的方法，则父类方法上的注解不会被继承；否则可以继承
                Annotation[] annotations1 = method.getAnnotations();
                System.out.println(annotations1);
            }
        }
        Method setDepartName = cls.getDeclaredMethod("setDepartName", String.class);
        Method getDepartName = cls.getDeclaredMethod("getDepartName");
        Depart depart = cls.getConstructor().newInstance();
        //执行方法
        setDepartName.invoke(depart, "111");
        System.out.println(getDepartName.invoke(depart));

        Field departName = cls.getDeclaredField("departName");
        //设置访问权限为可访问
        departName.setAccessible(true);
        //获取属性的值
        System.out.println(departName.get(depart));

        //自身public构造函数
        Constructor<?>[] constructors = cls.getConstructors();
        //自身所有构造函数
        Constructor<?>[] declaredConstructors = cls.getDeclaredConstructors();

        // 参数的类型 是否 为调用者的子类型 或者 相同类型
        System.out.println(Depart.class.isAssignableFrom(ParentDepart.class)); // false
        System.out.println(Depart.class.isAssignableFrom(Depart.class)); // true
        System.out.println(ParentDepart.class.isAssignableFrom(Depart.class)); // true
        System.out.println(ParentDepartInterface.class.isAssignableFrom(Depart.class)); // true
    }
}
